package com.tanklab.signature.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.tanklab.signature.common.util.JwtUtils;
import com.tanklab.signature.common.util.ResultCode;
//import com.tanklab.signature.common.util.TokenBlacklistManager;
import com.tanklab.signature.ds.resp.CommonResp;
import com.tanklab.signature.ds.resp.vo.TokenRefreshVo;
import com.tanklab.signature.entity.User;
import com.tanklab.signature.mapper.UserMapper;
import com.tanklab.signature.service.WeChatAuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class WeChatAuthServiceImpl implements WeChatAuthService {

    @Value("${wechat.appid}")
    private String appId;

    @Value("${wechat.secret}")
    private String appSecret;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private UserMapper userMapper;

    private final RestTemplate restTemplate = new RestTemplate();
    @Autowired
    private ObjectMapper objectMapper;

//    @Autowired
//    private TokenBlacklistManager blacklistManager;

    // 微信登录流程，返回访问Token和刷新Token
    @Override
    public CommonResp<TokenRefreshVo> login(String code) {
        CommonResp<TokenRefreshVo> authresp = new CommonResp<>();

        // 1. 调用微信API获取session信息
        Map<String, String> sessionInfo = null;
        try {
            sessionInfo = getWeChatSession(code);
        } catch (Exception e) {
            authresp.setRet(ResultCode.LOGIN_FAIL);
            authresp.setMsg("微信登录失败: " + e.getMessage());
            return authresp;
        }

        String openid = sessionInfo.get("openid");
        String sessionKey = sessionInfo.get("session_key");

        // 2. 查询或创建用户
        User user = userMapper.selectById(openid);
        if (user == null) {
            user = new User();
            user.setOpenid(openid);
            user.setCreateTime(new Date());
            user.setLastLoginTime(new Date());
            userMapper.insert(user);
        }

        // 3. 更新会话密钥（加密存储）
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("openid", openid);

        user.setSessionKey(encryptSessionKey(sessionKey));
        user.setLastLoginTime(new Date());
        userMapper.update(user, wrapper);

        // 4. 生成JWT令牌和刷新令牌
        String token = jwtUtils.generateToken(openid);
        String refreshToken = jwtUtils.generateRefreshToken(openid);

        // 计算过期时间
        Date now = new Date();
        int expiresIn = (int)(jwtUtils.getExpiration() / 1000);    // 转换为秒

        // 5. 封装响应
        TokenRefreshVo tokenData = new TokenRefreshVo();
        tokenData.setToken(token);
        tokenData.setRefreshToken(refreshToken);
        tokenData.setExpiresIn(expiresIn);

        authresp.setData(tokenData);
        authresp.setRet(ResultCode.SUCCESS);
        return authresp;
    }

    /**
     * 刷新Token
     * @param refreshToken 刷新令牌
     * @return 新的访问令牌和刷新令牌
     */
    @Override
    public CommonResp<TokenRefreshVo> refreshToken(String refreshToken) {
        CommonResp<TokenRefreshVo> response = new CommonResp<>();

        // 验证刷新令牌有效性
        if (!jwtUtils.validateRefreshToken(refreshToken)) {
            response.setRet(ResultCode.TOKEN_INVALID);
            response.setMsg("刷新令牌无效或已过期");
            return response;
        }

        // 从刷新令牌中获取用户openid
        String openid = jwtUtils.getOpenidFromToken(refreshToken);
        System.out.println("openid: " + openid);

        // 检查用户是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("openid", openid);
        User user = userMapper.selectOne(queryWrapper);

        if (user == null) {
            response.setRet(ResultCode.USER_NOT_EXIST);
            response.setMsg("用户不存在");
            return response;
        }

        // 生成新的令牌和刷新令牌
        String newToken = jwtUtils.generateToken(openid);
        String newRefreshToken = jwtUtils.generateRefreshToken(openid);

        TokenRefreshVo tokenData = new TokenRefreshVo();
        tokenData.setToken(newToken);
        tokenData.setRefreshToken(newRefreshToken);

        response.setRet(ResultCode.SUCCESS);
        response.setData(tokenData);
        return response;
    }

    /**
     * 从token中获取openid
     */
    @Override
    public String getOpenidFromToken(String token) {
        return jwtUtils.getOpenidFromToken(token);
    }

    // Deprecated
//    @Override
//    public CommonResp logout(HttpServletRequest request) {
//        CommonResp resp = new CommonResp();
//
//        // 获取请求中的token
//        String token = request.getHeader("Authorization");
//        if (token != null && token.startsWith("Bearer ")) {
//            token = token.substring(7);
//
//            try {
//                // 解析token获取过期时间
//                long expireTime = jwtUtils.getExpirationTimeFromToken(token);
//
//                // 将token加入黑名单
//                blacklistManager.addToBlacklist(token, expireTime);
//
//                resp.setRet(ResultCode.SUCCESS);
//                resp.setMsg("已成功登出");
//            } catch (Exception e) {
//                resp.setRet(ResultCode.ERROR);
//                resp.setMsg("登出失败: " + e.getMessage());
//            }
//        } else {
//            resp.setRet(ResultCode.TOKEN_MISS);
//            resp.setMsg("未提供有效的token");
//        }
//
//        return resp;
//    }

    /**
     * 获取微信session信息
     */
    public Map<String, String> getWeChatSession(String code) throws Exception {
        code = code.replace("\"", "").trim();
        String url = String.format(
                "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
                appId, appSecret, code
        );
        String response = restTemplate.getForObject(url, String.class);
        JsonNode json = objectMapper.readTree(response);

        if (json.has("errcode") && json.get("errcode").asInt() != 0) {
            throw new RuntimeException("微信登录失败: " + json.get("errmsg").asText());
        }

        Map<String, String> result = new HashMap<>();
        result.put("openid", json.get("openid").asText());
        result.put("session_key", json.get("session_key").asText());
        return result;
    }

    /**
     * 加密sessionKey
     */
    private String encryptSessionKey(String sessionKey) {
        return new BCryptPasswordEncoder().encode(sessionKey);
    }
}
